package aufgabe2.worker;

import static akka.actor.Actors.remote;

import java.math.BigInteger;
import java.net.InetAddress;
import java.util.ArrayList;

import akka.actor.ActorRef;
import akka.actor.UntypedActor;
import aufagabe2.master.DataMessage;

public class Worker extends UntypedActor {
	private static int idGenerator = 0;
	private int actorId;
	private ArrayList<BigInteger> rlist = new ArrayList<BigInteger>();
	private CalculateMessage calculateMessage;
	private BigInteger toFactorize;
	private boolean initialized = false;
	private boolean ended=false; //the factorization isn't terminated
	private Treatment treatment=null;
	
	public Worker() {
		//Important : When the ID isn't fixed, it will be always the same
		//instance used of the Actor for all the Remote call of a client
		getContext().setId(idGenerator + "");
		actorId = idGenerator;
		System.out.println("Actor was created: id=" + idGenerator);
		idGenerator++;
	}
	
	private ActorRef master;
		
	// message handler
	public void onReceive(Object message) {
		
		if (message instanceof CalculateMessage) 
		{
			if (!initialized){
				this.master = getContext().getSender().get();
			}
				calculateMessage = (CalculateMessage) message;//convert the message into a CalculateMessage
				treatment = new Treatment(calculateMessage,calculateMessage.getCalculId(),master);
				Thread t = new Thread(treatment);
				t.start();
				initialized=true;

		} 
		else if (message instanceof DataMessage) //new worker
		{
			this.master = getContext().getSender().get();
			
			this.master.tell((DataMessage) message);
		}
		else if (message instanceof ResultMessage)
		{
			try{
					ended = treatment.ended;
					rlist = Treatment.rlist;
					toFactorize=treatment.toFactorize;
					ResultMessage rm = (ResultMessage) message;//convert message into a ResultMessage
					calculateMessage.setCalculId(rm.getCalculId());
				
				if(!ended)//factorization not finished
				{
					boolean unknownprime = true;
					//check if the factor found is not already on the results list
					for(BigInteger e : rlist){
						if(e.compareTo(rm.getToFactorize()) == 0) unknownprime = false;
					}
					if( unknownprime ){
						toFactorize.divide(rm.getToFactorize());
						rlist.add(rm.getToFactorize());
					}
					calculateMessage.setNumber(toFactorize);
						getContext().tell(calculateMessage);
				}
			}catch(Exception e)
			{
			}
		}
		else if (message instanceof TerminateMessage)
		{
			if(!ended)
			{
				if(treatment != null)
					treatment.stop();
			}
		}
		else 
		{
			throw new IllegalArgumentException("Unknown message [" +
			message + "]");
		}
	}
	
	@Override
	public void postStop() {
		System.out.println("Actor was ended: " + this.actorId);
		super.postStop();
	}
	
	public static void main(String[] args) throws Exception {
		ClientGUI gui = new ClientGUI(null,"Parameters",true);
		ArrayList<String> parameters = gui.showDialog();
		if(parameters != null)
		{
			 try{
                 remote().start(InetAddress.getLocalHost().getHostAddress(), Integer.parseInt(parameters.get(0)));
                 System.out.println("Worker:");
                 System.out.println("\tHost: " + InetAddress.getLocalHost().getHostAddress());
                 System.out.println("\tPort: " + parameters.get(0));
         }catch(Exception e)
         {
                 System.err.println("Error. Please verify the host and the port");
                 System.exit(-1);
         }

		}
		else
			System.exit(-1);
	}
}